module beep_hh #(parameter CLK_PRE = 50_000_000,TIME_300MS = 15_000_000)(
    
    input               clk         ,
    input               rst_n       ,
    input          key_in      ,
    output reg          pwm

);
    
    // 频率控制音色，占空比控制音量 占空比越大 低电平越少 音量越小

    parameter   DO = CLK_PRE /523,    // do的周期 所需要系统时钟周期的个数
                RE = CLK_PRE /587,    // re的周期 所需要系统时钟周期的个数
                MI = CLK_PRE /659,    // mi的周期 所需要系统时钟周期的个数
                FA = CLK_PRE /698,    // fa的周期 所需要系统时钟周期的个数
                SO = CLK_PRE /784,    // so的周期 所需要系统时钟周期的个数
                LA = CLK_PRE /880,    // la的周期 所需要系统时钟周期的个数
                XI = CLK_PRE /988;    // si的周期 所需要系统时钟周期的个数

    reg [16:0]  cnt1  ;    // 计数频率   
    wire add_cnt1     ;    
    wire end_cnt1     ;
    reg [16:0]  X;        // cnt1最大值

    reg [23:0] cnt2   ;    // 计数每个音符发声300ms
    wire add_cnt2     ;
    wire end_cnt2     ;

    reg [5:0] cnt3    ;    // 计数乐谱48     
    wire add_cnt3     ;
    wire end_cnt3     ;
    reg  en; // 是否播放音乐
    reg whitch; // 选择音乐

    reg ctrl ; // 对后 25% 消音
    



    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin en <= 0; whitch<=0; end
        else if(key_in == 1'b1) en <= 1'b1;
        else if(key_in == 1'b0) en <= 1'b0;
        else begin en <= en; whitch <= whitch; end
    end


    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)  cnt1 <= 0;
        else if(end_cnt2)
            cnt1 = 0;
        else if(add_cnt1)
            if (end_cnt1) cnt1 <=0;
            else cnt1 <= cnt1 + 1'b1;
        else 
            cnt1 <= cnt1;
    end
    assign add_cnt1 = en;
    assign end_cnt1 = add_cnt1 && cnt1 == X - 1;


    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)  cnt2 <= 0;
        else if(add_cnt2)
            if (end_cnt2) cnt2 <= 0; 
            else cnt2 <= cnt2 + 1'b1;
        else 
            cnt2 <= cnt2;
    end
    assign add_cnt2 = en;
    assign end_cnt2 = add_cnt2 && cnt2 == TIME_300MS - 1;


    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)  cnt3 <= 0;
        else if(add_cnt3)
            if (end_cnt3) cnt3 <=0;
            else cnt3 <= cnt3 + 1'b1;
        else 
            cnt3 <= cnt3;
    end
    assign add_cnt3 = end_cnt2;
    assign end_cnt3 = add_cnt3 && cnt3 == 48 - 1;



    always @(*) begin

            case(cnt3)

            0  : X = DO;
            1  : X = DO;
            2  : X = SO;
            3  : X = SO;

            4  : X = LA;
            5  : X = LA;
            6  : X = SO;
            7  : X = 1;

            8  : X = FA;
            9  : X = FA;
            10 : X = MI;
            11 : X = MI;

            12 : X = RE;
            13 : X = RE;
            14 : X = DO;
            15 : X = 1;

            16 : X = SO;
            17 : X = SO;
            18 : X = FA;
            19 : X = FA;

            20 : X = MI;
            21 : X = MI;
            22 : X = RE;
            23 : X = 1;

            24 : X = SO;
            25 : X = SO;
            26 : X = FA;
            27 : X = FA;

            28 : X = MI;
            29 : X = MI;
            30 : X = RE;
            31 : X = 1;

            32 : X = DO;
            33 : X = DO;
            34 : X = SO;
            35 : X = SO;

            36 : X = LA;
            37 : X = LA;
            38 : X = SO;
            39 : X = 1;

            40 : X = FA;
            41 : X = FA;
            42 : X = MI;
            43 : X = MI;

            44 : X = RE;
            45 : X = RE;
            46 : X = DO;
            47 : X = 1;


            default : X = 1;
            endcase



    end


    always @(posedge clk or negedge rst_n) begin
        
        if(!rst_n) 
            ctrl <= 0;
        else if (cnt2 >= ((TIME_300MS>>1) + (TIME_300MS>>2)))
            ctrl <= 1'b1;
        else if(X == 1)
            ctrl <= 1'b1;
        else
            ctrl <= 0;  
    end

    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)
            pwm <= 1'b1;
        else if(ctrl)
            pwm <= 1'b1;
        else if(cnt1 < X >> 4)
            pwm <= 0;
        else
            pwm <= 1'b1;
        
    end


endmodule